package com.ppch.wuwamanus.aop;

import com.ppch.wuwamanus.annotation.AuthCheck;
import com.ppch.wuwamanus.exception.BusinessException;
import com.ppch.wuwamanus.exception.ErrorCode;
import com.ppch.wuwamanus.model.entity.User;
import com.ppch.wuwamanus.model.enums.UserRoleEnum;
import com.ppch.wuwamanus.service.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * Package:ppch-picture-backend
 * ClassName:AuthInterceptor
 *
 * @Author 泡泡茶壶
 * @Create 2024/12/18 14:37
 * @Version 1.0
 * Description:
 * 用户权限校验切面，通过读取@AuthCheck注解的mustRole值，判断用户是否具有该权限
 */
@Aspect
@Component
@Slf4j
public class AuthInterceptor {

    @Resource
    private UserService userService;

    /**
     * @Around:环绕切面，在方法执行前后都可添加额外的逻辑
     * @Around("@annotation(authCheck)"):表示该切面只在使用了@AuthCheck注解的方法上生效
     */
    @Around("@annotation(authCheck)")
    public Object doInterceptor(ProceedingJoinPoint proceedingJoinPoint, AuthCheck authCheck) throws Throwable {
        //获取注解上的值：比如：user,admin,vip,svip
        String mustRole = authCheck.mustRole();
        //通过HttpServletRequest获取当前登录用户的角色信息
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest();
        //getLoginUser：从session中获取当前登录用户，如果未登录，会直接报错
        User loginUser = userService.getLoginUser(httpServletRequest);
        //获取注解中声明的角色信息
        UserRoleEnum mustRoleEnum = UserRoleEnum.getEnumByValue(mustRole);
        //如果枚举类对象为空，说明该方法不需要任何权限就可以调用，
        if(mustRoleEnum == null){
            //放行：调用被增强方法，并返回被增强方法的返回值
            return proceedingJoinPoint.proceed();
        }
        //以下代码必须具有某个角色才可通过
        //获取当前登录用户的角色信息
        String userRole = loginUser.getUserRole();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);
        //如果该方法需要管理员 admin 权限，但是角色又不是 管理员 ，报错提示无权限
        if(UserRoleEnum.ADMIN.equals(mustRoleEnum) && !UserRoleEnum.ADMIN.equals(userRoleEnum)){
            log.error("用户无 ADMIN 权限");
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        //校验通过，执行方法，并返回方法返回值
        return proceedingJoinPoint.proceed();
    }
}
